import pandas as pd
from sklearn import preprocessing
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import numpy as np
import random

from sklearn.manifold import TSNE
from pyecharts.charts import Bar,Page
from pyecharts import options as opts
from pyecharts.globals import ThemeType


'''
数据预处理
'''


#数据清洗
# 方法1读取指定文件名下数据
file_path = '含量2020.xlsx'
data = pd.read_excel(file_path, sheet_name='105hl')
df=pd.read_excel(file_path,sheet_name='110hl')

'''
数据处理分析 
'''

def insert():#录入105hl信息
    # #读取所有数据
    print('获取当前105hl所有值:\n{0}'.format(data))  # 格式化输出

def search():#录入110hl信息
    d=df.head(110)
    print('获取当前110hl所有值:\n{0}'.format(d))

def kkmeans():#110hl偏度分布
    # c=df.mean()#获取各数据平均值
    # print('获取当前110hl平均值:\n{0}'.format(c))
    c=[
        'Li','Be','F','Na','Mg','Al','Si','P','Cl','K','Ca','Ti','V','Cr','Mn','Fe','Co','Ni','Cu','Zn','As','Se','Br','Sr','Mo', 'Cd','Sb','I','Ba','W','Hg','Pb','Bi'
       ]
    c_var={}
    sc=[]
    for j in c:
        c_var[j]=abs(df[j].skew())
        sc=pd.Series(c_var).sort_values(ascending=True)
    print('110hl数据偏度分布:\n{0}'.format(sc))

def kmeans():  # 105hl偏度分布
    var=[
        'Zn','Ca','P','Na','Si','Mg','Al','Fe','Mn','Cu','Be','Cd','V','Ni',
        'Co','Ba','Sr','F','Cl','Br','I','Se','La','Ce','Pr','Nd','Sm','Eu',
        'Gd','Tb','Dy','Ho','Er','Tm','Yb','Lu','Y','Hg','Bi','Sb','As'
]  # var:variable-变量

    skew_var={}
    skew=[]
    for i in var:
        skew_var[i] = abs(data[i].skew())  # .skew()求该变量的偏度
        skew = pd.Series(skew_var).sort_values(ascending=False)
    print('105hl数据偏度分布:\n{0}'.format(skew))
    # d = data.mean()
    # print('获取当前105hl平均值:\n{0}'.format(d))


def deal():#105hl数据处理
    # 使用命令描述，我们将看到数据如何分布，最大值，最小值，均值……
    a = data.describe()
    print('105hl数据分布:\n{0}'.format(a))


def total():#110hl数据处理
    b = df.describe()
    print('110hl数据分布:\n{0}'.format(b))

'''
k-means的k就是最终聚集的簇数，这个要你事先自己指定。k-means在常见的机器学习算法中算是相当简单的，基本过程如下：

首先任取k个样本点作为k个簇的初始中心；
对每一个样本点，计算它们与k个中心的距离，把它归入距离最小的中心所在的簇；
等到所有的样本点归类完毕，重新计算k个簇的中心；
重复以上过程直至样本点归入的簇不再变动。
k-means聚类分析的原理虽然简单，但缺点也比较明显：

首先聚成几类这个k值你要自己定，但在对数据一无所知的情况下你自己也不知道k应该定多少；
初始质心也要自己选，而这个初始质心直接决定最终的聚类效果；
每一次迭代都要重新计算各个点与质心的距离，然后排序，时间成本较高。
值得一提的是，计算距离的方式有很多种，不一定非得是笛卡尔距离；计算距离前要归一化。
'''
def OZFHCA():#105hl聚类算法
    # #1.数据进行一定处理
    k=105#聚类类别
    iteration=500#最大循环次数
    data_zs=(data-data.mean())/data.std()#数据标准化 可以参考一下data.describe()
    data_zs.pop('药名')#用于删除最后非数据列
    # data_a=data_zs.assign(ZnMg=data_zs['Zn']/data_zs['Mg'])#最后添加一列数据
    # print(data_zs)
    #2.数据模型建立
    model=KMeans(n_clusters=k,max_iter=iteration)#并发数设为4,n_jobs=4
    model.fit(data_zs)
    #3.简单打印结果
    r1=pd.Series(model.labels_).value_counts()#统计各个类别数目
    r2=pd.DataFrame(model.cluster_centers_)#找出聚类中心
    r = pd.concat([r2,r1], axis=1)  # 1 横向连接 0 纵向连接
    r.columns=list(data_zs.columns)+[u'聚类类别']#重命名表头
    r.to_excel('聚类处理1.xlsx')
    print(r)
    # 详细输出原始数据及类别
    rx=pd.concat([data,pd.Series(model.labels_,index=data.index)],axis=1)#1 横向连接 0 纵向连接
    rx.columns=list(data.columns)+[u'聚类类别']
    rx.to_excel('原始聚类处理.xlsx')
    print(rx)

def OOZHCA():#110hl聚类算法
    # #1.数据进行一定处理
    k = 110  # 聚类类别
    iteration = 500  # 最大循环次数
    df_zx = (df - df.mean()) / df.std() # 数据标准化 可以参考一下data.describe()
    df_zx.pop('方剂名称')  # 用于删除最后非数据列
    c=df_zx[:110].T.T #类似于多维数组，T 属性（即 transpose 函数）可以转置 DataFrame这样就可以去除空值
    # data_a=data_zs.assign(ZnMg=data_zs['Zn']/data_zs['Mg'])#最后添加一列数据
    # print(c)
    # 2.数据模型建立
    model = KMeans(n_clusters=k, max_iter=iteration)  # 并发数设为4,n_jobs=4
    model.fit(c)
    # 3.简单打印结果
    r1 = pd.Series(model.labels_).value_counts()  # 统计各个类别数目
    r2 = pd.DataFrame(model.cluster_centers_)  # 找出聚类中心
    r = pd.concat([r2, r1], axis=1)  # 1 横向连接 0 纵向连接
    r.columns = list(c.columns) + [u'聚类类别']  # 重命名表头
    r.to_excel('聚类处理2.xlsx')
    print(r)
    # 详细输出原始数据及类别 由于excel列表有超出，所以就用c下面的空间保存数据
    rx = pd.concat([df, pd.Series(model.labels_, index=c.index)], axis=1)  # 1 横向连接 0 纵向连接
    rx.columns = list(df.columns) + [u'聚类类别']
    rx.to_excel('原始聚类处理1.xlsx')
    print(rx)

#柱状图绘制
def barPage()->Bar:
    path='原始聚类处理.xlsx'
    dat=pd.read_excel(path,sheet_name='Sheet1')
    bar=(
        Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
        .add_xaxis(dat['药名'].tolist())
        .add_yaxis('模式类别',dat['聚类类别'].tolist())
        .set_global_opts(
             title_opts=opts.TitleOpts(title='聚类分析图'),
             legend_opts=opts.LegendOpts(is_show=False),
             toolbox_opts=opts.ToolboxOpts()
        )
    )
    print('HTML网页端创建成功,请前往网页端查看...')
    return bar

def barPage2()->Bar:
    path='原始聚类处理1.xlsx'
    dat=pd.read_excel(path,sheet_name='Sheet1')
    bar=(
        Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
        .add_xaxis(dat['方剂名称'].tolist())
        .add_yaxis('模式类别',dat['聚类类别'].tolist())
        .set_global_opts(
             title_opts=opts.TitleOpts(title='聚类分析图'),
             legend_opts=opts.LegendOpts(is_show=False),
             toolbox_opts=opts.ToolboxOpts()
        )
    )
    print('HTML网页端创建成功,请前往网页端查看...')
    return bar

def main():
    while True:
        menu()
        choice=int(input('请选择:'))
        if choice in [0,1,2,3,4,5,6,7,8,9,10]:
            if choice==0:
                answer=input('您确定有退出系统吗？y/n:')
                if answer=='Y' or answer=='y':
                    print('******************谢谢使用AM数据处理分析平台***********')
                    print('*********************该系统由AM版权所有***********')
                    break #退出系统
                elif answer=='N' or answer=='n':
                    print('***************感谢你的信任,AM数据处理分析平台欢迎你***************')
                    print('***************AM数据处理分析平台,使用K-means聚类***************')
                    continue
            elif choice == 1:
                insert()#录入105hl信息
            elif choice == 2:
                search()#录入110hl信息
            elif choice == 3:
                kmeans()#105hl偏度分布
            elif choice == 4:
                kkmeans()#110hl偏度分布
            elif choice == 5:
                 deal()#105hl数据处理
            elif choice == 6:
                 total()#110hl数据处理
            elif choice == 7:
                 OZFHCA()#105hl聚类算法 K-means
            elif choice == 8:
                 OOZHCA()#110hl聚类算法 K-means
            elif choice == 9:
                 barPage().render('index.html')#可视化显示
            elif choice == 10:
                 barPage2().render('demo.html')#可视化显示
def menu():
    print('========================AM数据处理分析平台=========================')
    print('-----------------------------功能菜单--------------------------------')
    print('\t\t\t\t\t\t1.录入105hl数据')
    print('\t\t\t\t\t\t2.录入110hl数据')
    print('\t\t\t\t\t\t3.105hl偏度分布')
    print('\t\t\t\t\t\t4.110hl偏度分布')
    print('\t\t\t\t\t\t5.105hl数据处理')
    print('\t\t\t\t\t\t6.110hl数据处理')
    print('\t\t\t\t\t\t7.105hl聚类算法')
    print('\t\t\t\t\t\t8.110hl聚类算法')
    print('\t\t\t\t\t\t9.105hl数据展示')
    print('\t\t\t\t\t\t10.110hl数据展示')
    print('\t\t\t\t\t\t0.退出AM处理平台')
    print('---------------------------------------------------------------')
if __name__=='__main__':
    main()